package ru.spb.osll.myfit.client.manager;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import ru.spb.osll.myfit.client.service.PageExecutingService;
import ru.spb.osll.myfit.client.service.PageExecutingServiceAsync;
import ru.spb.osll.myfit.client.widget.PageExecutingListener;
import ru.spb.osll.myfit.common.PageExecutingResult;
import ru.spb.osll.myfit.common.PageExecutingResult.PageExecutingState;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

public class PageExecutingManager {

  private final PageExecutingServiceAsync m_pageExecutingService = GWT
      .create(PageExecutingService.class);

  private HashMap<String, List<PageExecutingListener>> myListeners = new HashMap<String, List<PageExecutingListener>>();

  private HashMap<String, Timer> myTimers = new HashMap<String, Timer>();

  public PageExecutingManager() {

  }

  public void executeTestPage(final List<PageExecutingListener> listeners,
                              String pagePath) {
    m_pageExecutingService.executePage(pagePath,
        new AsyncCallback<PageExecutingResult>() {

          @Override
          public void onSuccess(PageExecutingResult pageExecutingResult) {

            PageExecutingState currentState = pageExecutingResult.getState();

            if (currentState == PageExecutingState.FINISH) {
              for (PageExecutingListener listener : listeners) {
                listener.processPageExecutingResult(pageExecutingResult);
                listener.finish();
              }
              return;
            }

            if (currentState != PageExecutingState.FAIL) {
              for (PageExecutingListener listener : listeners) {
                listener.processPageExecutingResult(pageExecutingResult);
              }

              final String id = pageExecutingResult.getID();
              myListeners.put(id, listeners);
              Timer timer = new Timer() {

                @Override
                public void run() {
                  processExecutingPage(id);
                }
              };
              myTimers.put(id, timer);
              timer.scheduleRepeating(1000);
            }
          }

          @Override
          public void onFailure(Throwable arg0) {

          }
        });

  }

  public void addResultToListen(final PageExecutingResult result,
                                int timerRepeating) {
    String id = result.getID();
    if (myTimers.get(id) == null) {
      Timer timer = new Timer() {

        @Override
        public void run() {
          processExecutingPage(result.getID());
        }
      };
      myTimers.put(result.getID(), timer);
      timer.scheduleRepeating(timerRepeating);
    }
  }

  public void addResultToListen(final PageExecutingResult result) {
    addResultToListen(result, 1000);
  }

  public void addListener(String id, PageExecutingListener listener) {
    List<PageExecutingListener> listeners = myListeners.get(id);
    if (listeners == null) {
      listeners = new LinkedList<PageExecutingListener>();
    }
    listeners.add(listener);
    myListeners.put(id, listeners);
  }

  private void processExecutingPage(String id) {
    m_pageExecutingService.getExecutingResult(id,
        new AsyncCallback<PageExecutingResult>() {

          @Override
          public void onFailure(Throwable arg0) {

          }

          @Override
          public void onSuccess(PageExecutingResult pageExecutingResult) {
            if (pageExecutingResult != null) {
              String id = pageExecutingResult.getID();
              List<PageExecutingListener> listeners = myListeners.get(id);
              if (pageExecutingResult.getState() == PageExecutingState.FINISH) {

                myTimers.get(id).cancel();

                for (PageExecutingListener listener : listeners) {
                  listener.processPageExecutingResult(pageExecutingResult);
                  listener.finish();
                }

              } else {
                for (PageExecutingListener listener : listeners) {
                  listener.processPageExecutingResult(pageExecutingResult);
                }
              }
            }
          }
        });
  }
}
